#include "com_sunson_sst_util_LocalSqlite.h"
#include "DB/DBConfig.h"
#include "Str/StringOperate.h"
#include "Log/CLog.h"
#include "Serial/CSerial.h"
#include <android/log.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zconf.h>
#include <unistd.h>

using namespace std;

#define TAG "NMD050-jni"                                                    // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)    // 定义LOGD类型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)    // 定义LOGI类型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)    // 定义LOGW类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)    // 定义LOGE类型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)    // 定义LOGF类型

#ifdef __cplusplus
extern "C" {
#endif

CDBConfig g_DB;
CLog g_Log;
SUNSON_CSerial::CSerial g_Com;

typedef ThreadMutex MUTEX_TYPE;
MUTEX_TYPE g_mtx;

/*
 * Class:     com_sunson_android_jni_Util_LocalSqlite
 * Method:    Open
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_sunson_sst_util_LocalSqlite_Open
        (JNIEnv *env, jobject, jstring dbName) {
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    return g_DB.IniDBConf(jstringTostring(env, dbName).c_str());
}

/*
 * Class:     com_sunson_android_jni_Util_LocalSqlite
 * Method:    ExcuteSQL
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_sunson_sst_util_LocalSqlite_ExcuteSQL
        (JNIEnv *env, jobject, jstring jsSQL) {
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    return g_DB.Sqlite_ExcuteSQL(jstringTostring(env, jsSQL).c_str());
}

/*
 * Class:     com_sunson_android_jni_Util_LocalSqlite
 * Method:    ExcuteInquery
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_sunson_sst_util_LocalSqlite_ExcuteInquery
        (JNIEnv *env, jobject, jstring jsSQL) {
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    g_Log.SetLogInfo(15, "/sdcard/YJ_Health/Log", "YJ_Bed", 200, 90);
    string strtmp = g_DB.Sqlite_InquireSQL(jstringTostring(env, jsSQL).c_str());

    char *strlog = new char[strlen(strtmp.c_str())];
    //g_Log.WriteLog(API_LOG_LEVEL,"inquery reslut[%s]",strlog);

    //g_Log.WriteLog(API_LOG_LEVEL,g_DB.Sqlite_InquireSQL(jstringTostring(env,jsSQL).c_str()).c_str());

    //return env->NewStringUTF(g_DB.Sqlite_InquireSQL(jstringTostring(env,jsSQL).c_str()).c_str());
    jstring jstr = env->NewStringUTF(strtmp.c_str());

    return jstr;
}

JNIEXPORT jint JNICALL Java_com_sunson_sst_util_LocalSqlite_WriteLog
        (JNIEnv *env, jobject, jint LogLevel, jstring jsLog) {
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    return g_Log.WriteLog(LogLevel, jstringTostring(env, jsLog).c_str());
}

JNIEXPORT void JNICALL Java_com_sunson_sst_util_LocalSqlite_SetLogInfo
        (JNIEnv *env, jobject, jint LogLevel, jstring pFileLocation, jstring pFileName,
         jint iMaxSize, jint iKeepingDate) {
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    return g_Log.SetLogInfo(LogLevel, jstringTostring(env, pFileLocation).c_str(),
                            jstringTostring(env, pFileName).c_str(), iMaxSize, iKeepingDate);
}

JNIEXPORT jint JNICALL
Java_com_yj_nursingded_device_MainControlBoard_MB_1OpenDevice(JNIEnv *env, jobject thiz,
                                                              jstring dev_name, jlong l_baud_rate,
                                                              jint stopbits, jchar parity) {
    // TODO: implement MB_OpenDevice()
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    g_Log.WriteLog(API_LOG_LEVEL,"MB_OpenDevice,dev_name = %s,l_baud_rate = %d",jstringTostring(env, dev_name).c_str(),l_baud_rate);
    return g_Com.OpenPort(jstringTostring(env, dev_name).c_str(),l_baud_rate);
}

JNIEXPORT jint JNICALL
Java_com_yj_nursingded_device_MainControlBoard_MB_1CloseDevice(JNIEnv *env, jobject thiz) {
    // TODO: implement MB_CloseDevice()
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    g_Com.ClosePort();
    return 0;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_yj_nursingded_device_MainControlBoard_MB_1WriteSerial(JNIEnv *env, jobject thiz,
                                                               jstring send_buf) {
    // TODO: implement MB_WriteSerial()
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    unsigned char AsciiStr[1024] = {0};
    int nLen = HexStr_ASCIIStr((unsigned char *)jstringTostring(env, send_buf).c_str(),AsciiStr);
    return g_Com.Write_Comm(AsciiStr,nLen);
}

JNIEXPORT jint JNICALL
Java_com_yj_nursingded_device_MainControlBoard_MB_1ReadSerial(JNIEnv *env, jobject thiz,
                                                              jint n_read, jbyteArray read_buf) {
    // TODO: implement MB_ReadSerial()
    unsigned char ReadBuf[1024] = {0};
    int nRet = g_Com.Read_Comm(ReadBuf,(int)n_read);
    if (nRet == n_read) {
        unsigned char HexData[1024] = {0};
        ASCIIStr_HexStr(ReadBuf,HexData,nRet);
        env->SetByteArrayRegion(read_buf, 0, (int)strlen((char *)HexData), (jbyte *) HexData);
    }
    return nRet;
}

JNIEXPORT jint JNICALL
Java_com_yj_nursingded_device_MainControlBoard_MB_1Reset(JNIEnv *env, jobject thiz) {
    // TODO: implement MB_Reset()
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    return 0;
}

int ExcCMd(unsigned char* ucCmd,int nLen,unsigned char * errorinfo,int TimeOut = 30)
{
    AUTO_GUARD(gd,MUTEX_TYPE,g_mtx);
    int nRet = g_Com.Write_Comm(ucCmd,nLen);
    if(nRet == nLen){
        unsigned char ucConnect[64] = {0};
        time_t start_time = time(NULL);
        int i = 0;
        while(1)
        {
            if ((time(NULL) - start_time) > TimeOut)
            {
                //g_SIULog.WriteLog(API_LOG_LEVEL,"Read Serial Data Time Out Exit");
                break;
            }
            i = g_Com.Read_Comm(ucConnect,1);
            if (i <=0 || ucConnect[0] != 0xA5)
                continue;
            else
                break;
        }

        if(ucConnect[0] != 0xA5) //head
            return -1;

        unsigned char strLog[1024] = {0};

        i = g_Com.Read_Comm(ucConnect,3);  // cmd(1) + len(2)
        //
        i = g_Com.Read_Comm(ucConnect,nLen+3);
        if(ucConnect[0] == 0x53)
        {
            return 0;
        } else{
            return -1;
        }
    }
    return -1;
}

int CalcXOR(unsigned char *ucData,int len)
{
    unsigned char ucXOR = 0x00;
    for(int i=0; i<len; i++)
    {
        ucXOR ^= ucData[i];
    }
    return ucXOR;
}

JNIEXPORT jint JNICALL
Java_com_yj_nursingded_device_MainControlBoard_MB_1RunCommand(JNIEnv *env, jobject thiz, jint n_cmd,
                                                              jstring param,
                                                              jbyteArray return_info) {
    // TODO: implement MB_RunCommand()
    g_Log.WriteLog(API_LOG_LEVEL,"RunCommand[%02x],Param = %s",n_cmd,jstringTostring(env, param).c_str());
    unsigned char ucReturnInfo[1024] = {0};
    unsigned char BufCmd[1024] = {0};
    switch (n_cmd)
    {
        case 0x10: //起背
            memcpy(BufCmd,"\x5A\x10\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x11: //平躺
            memcpy(BufCmd,"\x5A\x11\x00\x02\x00\x00\x00\x49\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x12: //左侧翻
            memcpy(BufCmd,"\x5A\x12\x00\x02\x00\x00\x00\x4A\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x13: //右侧翻
            memcpy(BufCmd,"\x5A\x13\x00\x02\x00\x00\x00\x4B\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x14: //抬腿
            memcpy(BufCmd,"\x5A\x14\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x15: //落腿
            memcpy(BufCmd,"\x5A\x15\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x19: //急停
            memcpy(BufCmd,"\x5A\x19\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x1A: //复原
            memcpy(BufCmd,"\x5A\x1A\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x1B: //清除数据
            memcpy(BufCmd,"\x5A\x1B\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
        case 0x1C: //模式设置
            memcpy(BufCmd,"\x5A\x1C\x00\x02\x00\x00\x00\x48\x55",9);
            BufCmd[7] = CalcXOR(BufCmd,6);
            return ExcCMd(BufCmd,9,ucReturnInfo);
    }
}

#ifdef __cplusplus
}
#endif
